package stmlib;

/**
 * A transactional Variable that points to an immutable value, e.g. an Integer or a String.
 * A Var can be made to point to different objects of the same type, but the objects pointed to
 * should never be modified because they may be get() concurrently by more than one thread.
 * If you need to make a mutable object transaction-safe, use a Ref instead.
 */
public class Var<E> extends Lockable {
    protected E value;
    public Var(E initialValue) { value = initialValue; lm = new LockManager(); }
    public Var() { this(null); }

    /** Read the value held by the Var.  Holds a get lock until the transaction is over. */
    public E get() { lm.readLock(); return value; }

    /**
     * Holds an exclusive lock until the transaction is over.
     * @param newValue the new value of the variable.
     */
    public void set(E newValue) {
        lm.writeLock();
        final E oldValue = value;
        
        lm.logUndo(new Runnable() {
            public void run() { value = oldValue; }
        });
        
        value = newValue;
    }

    /** Read the latest version of the variable without acquiring any locks. Unsafe!!! */
    public E peek() { return value; }

    public Var<E> lock() { lm.writeLock(); return this; }

    public String toString() { return toString(value); }
}